package com.syqc.monitor.ui.singlemap


import android.Manifest
import android.annotation.SuppressLint
import android.content.Intent
import android.graphics.Color
import androidx.activity.viewModels
import androidx.core.view.isVisible
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager
import autodispose2.autoDispose
import com.amap.api.maps.AMap
import com.amap.api.maps.CameraUpdateFactory
import com.amap.api.maps.model.LatLng
import com.amap.api.maps.model.LatLngBounds
import com.amap.api.maps.model.Marker
import com.amap.api.maps.model.PolylineOptions
import com.google.gson.reflect.TypeToken
import com.gyf.immersionbar.ktx.immersionBar
import com.permissionx.guolindev.PermissionX
import com.syqc.maps.utils.MapUtil
import com.syqc.adapter.CarInfoAdapter
import com.syqc.adapter.OperInfoAdapter
import com.syqc.base.BaseMapActivity
import com.syqc.choose.car.ChooseCarActivity
import com.syqc.choose.teamcar.TeamsCarsActivity
import com.syqc.comlib.AppConfigs
import com.syqc.comlib.MenuKey
import com.syqc.comlib.UserConstant
import com.syqc.comlib.databinding.IncludeToolbarBinding
import com.syqc.comlib.rx.LiveDataBus
import com.syqc.comlib.rx.filterFast
import com.syqc.comlib.utils.ActivityResultUtil.launchAct
import com.syqc.comlib.utils.ActivityResultUtil.registerResultOk
import com.syqc.comlib.utils.GsonUtil
import com.syqc.comlib.utils.Language
import com.syqc.comlib.utils.ToolbarHelper
import com.syqc.comlib.utils.showToast
import com.syqc.comlib.utils.startActivityTo
import com.syqc.comlib.utils.toast
import com.syqc.entity.GpsDetail
import com.syqc.login.FunKey
import com.syqc.login.FunType
import com.syqc.login.InfoSetModel
import com.syqc.login.LocationStatusModel
import com.syqc.maps.utils.BitmapUtil
import com.syqc.maps.utils.MarkerSet
import com.syqc.maps.utils.NaviActivity
import com.syqc.monitor.R
import com.syqc.monitor.databinding.ActivitySingleMap2Binding
import com.syqc.monitor.databinding.IncludeCarMapInfoBinding
import com.syqc.monitor.databinding.IncludeMapPlateTrafficBinding
import com.syqc.monitor.popup.DriversPopup
import com.syqc.monitor.ui.carinfo.CarInfoActivity
import com.syqc.monitor.ui.set.InfoSet2Activity
import com.syqc.monitor.ui.tyre.TyreInfoActivity
import com.syqc.monitor.utils.ActivityUtil
import com.syqc.utils.ColorUtil
import com.syqc.utils.DataUtil
import com.syqc.utils.Keys
import com.syqc.utils.NetDataUtil
import com.syqc.utils.ToolsUtil
import com.syqc.utils.Units
import com.syqc.videos.TalkPopup
import com.syqc.videos.TalkStatus
import com.syqc.videos.TalkbackUtil
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers

/** @Author Jasper @Time 2020/12/4 @Desc */
class SingleMapActivity :
    BaseMapActivity<ActivitySingleMap2Binding>(ActivitySingleMap2Binding::inflate) {
    private lateinit var mMapStateVB: IncludeMapPlateTrafficBinding
    private lateinit var mBarVB: IncludeToolbarBinding
    private lateinit var mInfoVB: IncludeCarMapInfoBinding
    private var mMarker: Marker? = null

    //最后一个定位点坐标
    private var lastLatLng: LatLng? = null
    private var startLatLng: LatLng? = null
    private var endLatLng: LatLng? = null

    //是否开始跟踪
    private var isStart = false

    //是否展示彈窗
    private var isShowPopup = true

    //是否移动到
    private var isMove = true

    //定位点集合
    private val lines = ArrayList<LatLng>()
    private val mOption: PolylineOptions by lazy { PolylineOptions() }

    private val mDriversPopup by lazy { DriversPopup(this) }
    private val mViewModel: SingleMapViewModel by viewModels()
    override fun initMap() {
        initMapSetting()
    }

    override fun initView() {
        mMapStateVB = IncludeMapPlateTrafficBinding.bind(binding.root)
        mBarVB = IncludeToolbarBinding.bind(binding.root)
        mInfoVB = IncludeCarMapInfoBinding.bind(binding.root)
        ToolbarHelper.setToolbar(this, R.string.title_monitor_single)
        immersionBar { titleBar(mBarVB.mToolbar) }
        initViewModel()
        initIntent()
        infoView()
        infoEvent()
        BitmapUtil.initLruCache()
    }

    private fun initIntent() {
        val carId = intent.getStringExtra(Keys.INTENT_CAR_ID)
        val carName = intent.getStringExtra(Keys.INTENT_PLATE) ?: ""
        if (carId == null) return
        mViewModel.carId = carId
        binding.lrvChooseCar.setRightText(carName)
        isStart = true
        mViewModel.startTime()
        binding.lrvChooseCar.isEnabled = false
    }

    private fun initMapSetting() {
        mAMap.run {
            MapUtil.initMapSetting(this)
            setOnMarkerClickListener {
                if (it.`object` == "marker")
                    return@setOnMarkerClickListener true
                isShowPopup = true
                mMapStateVB.tvCarCarShow.setText(R.string.desc_com_hide)
                mInfoVB.llCarInfo.isVisible = true
                return@setOnMarkerClickListener true
            }
            mapType = mViewModel.mMapType
            isTrafficEnabled = mViewModel.isCarTraffic
            mMapStateVB.ivCarTraffic.isSelected = mViewModel.isCarTraffic
        }
    }

    //是否已显示
    private var isShow = false
    private fun initViewModel() {
        if (mViewModel.isPlate) {
            mMapStateVB.tvCarCarState.setText(R.string.desc_car_plate)
        } else {
            mMapStateVB.tvCarCarState.setText(R.string.desc_car_name)
        }
        mViewModel.toastObserver().autoDispose(scopeProvider).subscribe(this::toastObserver)

        mViewModel.locationSub.hide().autoDispose(scopeProvider).subscribe({
            it.run {
                if (glat.isEmpty() || glng.isEmpty()) return@subscribe
                if (!isShow) {
                    toast(R.string.toast_single_start)
                    binding.btnSingleEnd.isSelected = true
                    binding.btnSingleStart.isSelected = false
                    isShow = true
                }
                val latLng = LatLng(it.glat.toDouble(), it.glng.toDouble())
                lastLatLng = latLng
                addLineOption(latLng)

                val bitmapDes =
                    MarkerSet.getBitmapDes(
                        this@SingleMapActivity,
                        carId, state, drct, carName, carPlate, iconLink, mViewModel.isPlate, speed
                    )
                if (mMarker == null) {
                    MapUtil.addGetMarker(
                        mAMap,
                        latLng,
                        if (Language.isEnglish()) R.mipmap.ic_marker_start_e else R.mipmap.ic_marker_start
                    ).`object` =
                        "marker"
                    mMarker = MapUtil.addAndGetMarker(mAMap, latLng, bitmapDes)
                    startLatLng = latLng
                } else {
                    mMarker?.position = latLng
                    mMarker?.setIcon(bitmapDes)
                }
                if (isShowPopup) {
                    mInfoVB.llCarInfo.isVisible = true
                    initInfo()
                }
                MapUtil.showMapLatLng(mAMap, latLng)
            }
        }, {
            toast(it.message ?: getString(R.string.toast_no_back_error_info))
        })
        mViewModel.startLive.observe(this) {
            isStart = false
        }

        //时间刷新监听
        mViewModel.timeObserver().observeOn(AndroidSchedulers.mainThread())
            .autoDispose(scopeProvider).subscribe {
                if (it == 1) {
                    ToolsUtil.stopAmin(binding.ivRefresh)
                    ToolsUtil.startAmin(binding.ivRefresh)
                }
                if (it / 3600 > 0) {
                    binding.tvRefreshTime.text = "${it / 60}${getString(R.string.unit_minute_)}"
                } else if (it / 60 > 0) {
                    binding.tvRefreshTime.text = "${it / 60}${getString(R.string.unit_minute_)}"
                } else {
                    binding.tvRefreshTime.text = "${it}${getString(R.string.unit_second_)}"
                }
            }
    }


    override fun setListener() {
//        binding.ivCarTimeSet.setOnClickListener {
//            mTimePopup.showPopup(window.decorView)
//        }

        mMapStateVB.tvCarMapState.filterFast {
            if (mViewModel.mMapType == AMap.MAP_TYPE_NORMAL) {
                mViewModel.mMapType = AMap.MAP_TYPE_SATELLITE
                mAMap.mapType = AMap.MAP_TYPE_SATELLITE
                mMapStateVB.tvCarMapState.setText(R.string.desc_com_map_state_satellite)
            } else {
                mViewModel.mMapType = AMap.MAP_TYPE_NORMAL
                mAMap.mapType = AMap.MAP_TYPE_NORMAL
                mMapStateVB.tvCarMapState.setText(R.string.desc_com_map_state_normal)
            }
        }

        mMapStateVB.tvCarCarState.filterFast {
            mViewModel.isPlate = !mViewModel.isPlate
            if (mViewModel.isPlate) {
                mMapStateVB.tvCarCarState.setText(R.string.desc_car_plate)
            } else {
                mMapStateVB.tvCarCarState.setText(R.string.desc_car_name)
            }
            mViewModel.refresh()
        }

        mMapStateVB.ivCarTraffic.filterFast {
            mViewModel.isCarTraffic = !mViewModel.isCarTraffic
            mMapStateVB.ivCarTraffic.isSelected = mViewModel.isCarTraffic
            mAMap.isTrafficEnabled = mViewModel.isCarTraffic

        }

        binding.lrvChooseCar.filterFast {
            if (!mViewModel.carId.isNullOrEmpty()) {
                isStart = false
                isShow = false
                mInfoVB.llCarInfo.isVisible = false
                stopMonitor()
                mViewModel.stopTime()
                ToolsUtil.stopAmin(binding.ivRefresh)
                binding.rlRefresh.isVisible = false
                binding.btnSingleStart.isSelected = true
                binding.btnSingleEnd.isSelected = false
            }
            if (NetDataUtil.isSyncTree) {
                launcher.launchAct<TeamsCarsActivity>(this)
            } else {
                launcher.launchAct<ChooseCarActivity>(this)
            }
        }

        binding.btnSingleStart.filterFast {
            if (mViewModel.carId.isNullOrEmpty()) {
                toast(R.string.hint_toast_choose_car)
                return@filterFast
            }
            if (isStart) {
                toast(R.string.toast_single_has_start)
                return@filterFast
            }
            if (!binding.btnSingleStart.isSelected) {
                R.string.toast_no_location_other.toast(this)
                return@filterFast
            }
            mAMap.clear()
            isStart = true
            mViewModel.startTime()
            binding.rlRefresh.isVisible = true
            ToolsUtil.startAmin(binding.ivRefresh)
            isShowPopup = true
            isMove = true
            mMapStateVB.tvCarCarShow.setText(R.string.desc_com_hide)
        }

        binding.btnSingleEnd.filterFast {
            if (mViewModel.carId.isNullOrEmpty()) {
                toast(R.string.hint_toast_choose_car)
                return@filterFast
            }
            if (!isStart) {
                toast(R.string.toast_single_not_start)
                return@filterFast
            }
            isStart = false
            isShow = false
            binding.btnSingleStart.isSelected = true
            binding.btnSingleEnd.isSelected = false
            mInfoVB.llCarInfo.isVisible = false
            toast(R.string.toast_single_stop)
            stopMonitor()
            mViewModel.stopTime()
            ToolsUtil.stopAmin(binding.ivRefresh)
            binding.rlRefresh.isVisible = false
        }
        mMapStateVB.tvCarCarShow.filterFast {
            if (!isStart) {
                toast(R.string.toast_single_not_start)
                return@filterFast
            }
            if (isShowPopup) {
                isShowPopup = false
                mMapStateVB.tvCarCarShow.setText(R.string.desc_com_display)
                mInfoVB.llCarInfo.isVisible = false
            } else {
                isShowPopup = true
                mMapStateVB.tvCarCarShow.setText(R.string.desc_com_hide)
                mInfoVB.llCarInfo.isVisible = true
            }
        }
        //放大
        binding.ivMapZoomIn.setOnClickListener {
            mAMap.animateCamera(CameraUpdateFactory.zoomOut(), 600, null)
        }

        //缩小
        binding.ivMapZoomOut.setOnClickListener {
            mAMap.animateCamera(CameraUpdateFactory.zoomIn(), 600, null)
        }
    }

    /** 划线 */
    private fun addLineOption(latLng: LatLng) {
        lines.add(latLng)
        mOption.color(Color.GREEN).width(15f).add(latLng)
        mAMap.addPolyline(mOption)
    }

    /** 停止 */
    private fun stopMonitor() {
        clearPointsAndMarker()
        lastLatLng?.let {
            MapUtil.addGetMarker(
                mAMap,
                it,
                if (Language.isEnglish()) R.mipmap.ic_marker_end_e else R.mipmap.ic_marker_end
            ).`object` = "marker"
        }
        endLatLng = lastLatLng
        if (startLatLng == null) return
        val builder = LatLngBounds.Builder()
        builder.include(startLatLng)
        builder.include(endLatLng)
        MapUtil.showMapBounds(mAMap, builder.build())
    }

    override fun onDestroy() {
        TalkbackUtil.destroy()
        super.onDestroy()
        clearPointsAndMarker()
        MarkerSet.recycleLruCache()
        lastLatLng = null
        lines.clear()
        mViewModel.stopTime()
        ToolsUtil.stopAmin(binding.ivRefresh)
        BitmapUtil.clearLruCache()
    }

    private fun clearPointsAndMarker() {
        mOption.points.clear()
        mInfoVB.llCarInfo.isVisible = false
        mMarker?.remove()
        mMarker = null
    }

    private val launcher = registerResultOk { result ->
        result.data?.let {
            mAMap.clear()
            val carId = it.getStringExtra(Keys.INTENT_CAR_ID)
            val carName = it.getStringExtra(Keys.INTENT_CAR_NAME) ?: ""
            binding.lrvChooseCar.setRightText(carName)
            mViewModel.carId = carId
            isShowPopup = true
            isMove = true
            isShow = false
            binding.btnSingleStart.isSelected = true
            mMapStateVB.tvCarCarShow.setText(R.string.desc_com_hide)
        }
    }


    //******************************************************************************************************
    private val runSpeed by lazy { getString(R.string.desc_run_speed) }
    private val dayMile by lazy { getString(R.string.desc_day_mile) }

    @SuppressLint("SetTextI18n")
    fun initInfo() {
        mViewModel.gpsDetail?.run {

            mInfoVB.tvCarRunSpeed.text = "$speed ${Units.speed}\n$runSpeed"
            mInfoVB.tvCarRunStop.text = runStopTime
            mInfoVB.tvCarDayMile.text = "$preMile ${Units.km}\n$dayMile"
            mInfoVB.tvCarTotalMile.text = "$mile ${Units.km}"
            mInfoVB.tvSatl.text = "${getString(R.string.desc_marker_loaction)}${satl.split("-")[0]}"
            mInfoVB.tvSgn.text = "${getString(R.string.desc_marker_sgn)}${sgn.split("-")[0]}"
            ColorUtil.lineState(mInfoVB.tvOnLine, state)
            val title = if (mViewModel.isPlate) carPlate else carName
            ColorUtil.setPlateColor(
                mInfoVB.tvPlateArea,
                mInfoVB.tvPlateNum,
                plateColor,
                plateColorCode,
                title
            )

            mInfoVB.tvCarTime.text = "${getString(R.string.desc_location_time)}：$time"
            val isTalk = mViewModel.talkChannel.isNotEmpty()
            if (isTalk != operInfoAdapter.isCanTalk)
                operInfoAdapter.isCanTalk = isTalk
        }
        if (isShowRecycler) {
            showInfoRecycler()
        }

    }

    private val mInfoAdapter by lazy { CarInfoAdapter() }
    private fun infoView() {
        mInfoVB.recyclerCarInfo.layoutManager = LinearLayoutManager(this)
        mInfoVB.recyclerCarInfo.adapter = mInfoAdapter

        handleOper()
    }

    private fun showInfoRecycler() {
        mInfoAdapter.setList(LocationStatusModel.upData(mViewModel.gpsDetail))
    }

    //是否展示列表
    private var isShowRecycler = AppConfigs.isMapInfoOpen

    /** 设置info点击事件 */
    private fun infoEvent() {
        LiveDataBus.get().with("upInfoState").observe(this) {
            if (mViewModel.carId.isNullOrEmpty()) return@observe
            mViewModel.refresh()
        }
        mInfoVB.ivUpDown.isSelected = isShowRecycler
        if (isShowRecycler) {
            showInfoRecycler()
            mInfoVB.recyclerCarInfo.isVisible = true
        } else {
            mInfoVB.recyclerCarInfo.isVisible = false
        }
        mInfoVB.ivTyre.isVisible = UserConstant.current_ip != "113.105.152.93"
        mInfoVB.ivUpDown.setOnClickListener {
            isShowRecycler = !isShowRecycler
            mInfoVB.ivUpDown.isSelected = isShowRecycler
            if (isShowRecycler) {
                showInfoRecycler()
                mInfoVB.recyclerCarInfo.isVisible = true
            } else {
                mInfoVB.recyclerCarInfo.isVisible = false
            }
        }


        mInfoVB.ivCarSet.setOnClickListener {
            if (ToolsUtil.isFastClick()) return@setOnClickListener
            startActivityTo<InfoSet2Activity>(this)
        }

        mInfoVB.ivCarClose.setOnClickListener {

            isShowPopup = false
            mMapStateVB.tvCarCarShow.setText(R.string.desc_com_display)
            mInfoVB.llCarInfo.isVisible = false
        }

        mInfoVB.ivCarRefresh.setOnClickListener {
            if (ToolsUtil.isFastClick()) return@setOnClickListener
            mViewModel.refresh2()
        }


        mInfoVB.ivTyre.setOnClickListener {
            mViewModel.gpsDetail?.let {
                val list = LocationStatusModel.getExtsValue(it.exts, "c8")
                if (list.isEmpty()) {
                    showToast(R.string.desc_toast_no_data_tyre)
                    return@setOnClickListener
                }
                val type = object : TypeToken<List<List<String>>>() {}
                val data: List<List<String>> = GsonUtil.gson.fromJson(list, type.type)
                DataUtil.psiTyres = data
                startActivityTo<TyreInfoActivity>(this) {
                    putExtra(Keys.INTENT_TITLE, if (mViewModel.isPlate) it.carPlate else it.carName)
                }
            }
        }
    }


    private fun startActivity(zClass: Class<*>, entity: GpsDetail?) {
        startActivity(
            Intent(this, zClass)
                .putExtra(Keys.INTENT_CAR_ID, entity?.carId)
                .putExtra(Keys.INTENT_PLATE, entity?.carPlate)
                .putExtra(Keys.INTENT_CAR_NAME, entity?.carName)
        )
    }

    override fun onResume() {
        super.onResume()
        if (isStart) {
            mViewModel.startTime()
            binding.rlRefresh.isVisible = true
            ToolsUtil.startAmin(binding.ivRefresh)
        }
        operInfoAdapter.setList(InfoSetModel.getChooseList(FunType.SINGLE))
    }


    ///////////////////////////////////////添加对讲//////////////////////////////////////////////////////
    //是否录音
    private var isRecord = true

    private val talkPopup by lazy {
        TalkPopup(this) {
            isRecord = true
            TalkbackUtil.closeTalk()
        }
    }
    private val operInfoAdapter by lazy { OperInfoAdapter(FunType.SINGLE) }

    private fun handleOper() {
        mInfoVB.rvType.isVisible = UserConstant.loginType == Keys.LOGIN_TYPE_USER
        mInfoVB.rvType.layoutManager = GridLayoutManager(this, 6)
        mInfoVB.rvType.adapter = operInfoAdapter
        operInfoAdapter.setList(InfoSetModel.getChooseList(FunType.SINGLE))
        operInfoAdapter.setOnItemClickListener { adapter, view, position ->
            val info = operInfoAdapter.data[position]
            if (!info.isCheckable) {
                R.string.toast_check_other_menu.toast(this)
                return@setOnItemClickListener
            }
            when (info.key) {
                FunKey.FUN_Talk -> {
                    if (!operInfoAdapter.isCanTalk) {
                        R.string.toast_no_channel.toast(this)
                        return@setOnItemClickListener
                    }
                    getAudioPermissions()
                }

                MenuKey.MENU_916 -> {
                    startActivityTo<CarInfoActivity>(this) {
                        putExtra(Keys.INTENT_CAR_ID, mViewModel.carId)
                    }
                }

                FunKey.FUN_NAVI -> {
                    mViewModel.gpsDetail?.run {
                        startActivityTo<NaviActivity>(this@SingleMapActivity) {
                            putExtra(Keys.INTENT_PLATE, carPlate)
                            putExtra("eLat", glat)
                            putExtra("eLng", glng)
                            putExtra("bLat", blat)
                            putExtra("bLng", blng)
                        }
                    }
                }

                FunKey.FUN_CALL -> {
                    if (mViewModel.driverInfo.isNotEmpty()) {
                        if (mViewModel.driverInfo.size == 1) {
                            ToolsUtil.talkPhone(
                                this,
                                mViewModel.driverInfo[0].driverPhone
                            )
                        } else {
                            mDriversPopup.show(
                                this.window.decorView,
                                mViewModel.driverInfo
                            )
                        }
                    } else {
                        R.string.desc_no_phone.toast(this)
                    }
                }

                else -> {
                    InfoSetModel.startFunActivity(
                        this,
                        ActivityUtil.getActivityByKey(info.key),
                        mViewModel.gpsDetail
                    )
                }
            }
        }

        TalkbackUtil.status.autoDispose(scopeProvider).subscribe {
            when (it) {
                TalkStatus.CLOSE -> {
                    talkPopup.setVoiceTitle(R.string.toast_audio_close)
                    talkPopup.dismiss()
                }

                TalkStatus.OPEN -> {
                    talkPopup.shouPopup(window.decorView)
                    talkPopup.setVoiceTitle(R.string.toast_audio_link)
                }

                TalkStatus.SUCCESS -> {
                    talkPopup.setVoiceTitle(R.string.toast_audio_talking)
                }

                TalkStatus.FAILURE -> {
                    talkPopup.setVoiceTitle(TalkbackUtil.toast)
                    mInfoVB.rvType.postDelayed({
                        talkPopup.dismiss()
                    }, 3000)
                }

                else -> {}
            }
        }
        //上传PCM数据网络失败监听
        TalkbackUtil.upload.autoDispose(scopeProvider).subscribe {
            isRecord = true
            TalkbackUtil.closeTalk()
            talkPopup.dismiss()
        }
        TalkbackUtil.image.autoDispose(scopeProvider).subscribe {
            talkPopup.setVoiceImage(it)
        }
        TalkbackUtil.toastLive.observeOn(AndroidSchedulers.mainThread()).autoDispose(scopeProvider)
            .subscribe {
                showToast(it)
            }
    }

    private fun getAudioPermissions() {
        PermissionX.init(this@SingleMapActivity).permissions(
            Manifest.permission.RECORD_AUDIO
        ).request { allGranted, grantedList, deniedList ->
            if (allGranted) {
                isRecord = false
                TalkbackUtil.openTalk(
                    this@SingleMapActivity,
                    mViewModel.carId ?: "",
                    mViewModel.talkChannel
                )
            } else {
                getString(
                    R.string.toast_persission_open,
                    getString(R.string.permission_audio)
                ).toast(this@SingleMapActivity)
            }
        }
    }
}